home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS01.ADF
/
C
/
freedraw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1985-11-15
|
33KB
|
819 lines
/************************************************************************/
/*** FreeDraw - PD graphics for Amiga ***/
/*** ***/
/*** This is an extremely simple graphics editor which works in ***/
/*** the windowing environment of the Amiga. It is very limited ***/
/*** in features, but I hope to add a lot more, and I would be ***/
/*** happy to receive assistance from anyone who wants to give it. ***/
/*** The basic idea of this program is to provide some minimal ***/
/*** image editing functions which can be used to develop images ***/
/*** for other programs. I know there will be a lot of Paint type ***/
/*** type programs avaialable soon, but what are we supposed to use ***/
/*** now? The most important features to add now will probably be ***/
/*** those related to "cut and paste", disk srtorage and retrieval, ***/
/*** and "single-pixel" editing like Mac's "fatbits". ***/
/*** I intend to use the IFF standard for the image storage and ***/
/*** retrieval and will be coding a "Files" menu soon. The work ***/
/*** required for "cut and paste" should be almost trivial, but I ***/
/*** still may not get to it for a while. Fatbits editing from one ***/
/*** window to another involves some manipulations of the RastPorts ***/
/*** which still elude me, as I have only recently begun to use the ***/
/*** Amiga and don't yet understand some important details of these ***/
/*** structures. This would be a great item for one of the genius ***/
/*** members of the Amiga programming community to provide. ***/
/*** There are only two menu topics in this version, so using it ***/
/*** is really quite easy. Boxes are not allowed to be drawn in ***/
/*** areas outside of the window where border gadgets are located, ***/
/*** and the pen-draw mode also clips to these same boundaries. If ***/
/*** you have begun to draw a box by clicking the left button while ***/
/*** the cursor is located in the FreeDraw window, then you can ***/
/*** cancel that box by clicking the right button. In the pen mode ***/
/*** pressing and holding the left button will draw. Colors are ***/
/*** selected by simply releasing the menu button over the desired ***/
/*** color in the Color menu. The erase feature always clears the ***/
/*** window to the currently selected color. ***/
/*** This is no gem of programming style, but you're getting it ***/
/*** for the right price so be patient with its design flaws. New ***/
/*** versions will appear here on BIX as soon as I can get them in ***/
/*** shape for release. I apologize to anyone who objects to my ***/
/*** lack of coding grace, but I just want to get the project off ***/
/*** the ground, and improvements will be forthcoming. There are ***/
/*** a lot of comments, but I didn't know what needed to be made ***/
/*** clear so I just commented everything. ***/
/*** ***/
/*** If you like the idea of a PD graphics program and would be ***/
/*** interested in doing some development work, then please write ***/
/*** me at the address listed below, or call if you prefer. I do ***/
/*** want to know if there is any interest in such a project, so ***/
/*** I will be glad to discuss any ideas you might have. Also, as ***/
/*** I do not currently use CompuServe or any other major nets, I ***/
/*** would appreciate if someone would post this listing there. ***/
/*** I hope somebody enjoys this. Have Fun. ***/
/*** Rick Ross 11/14/85 ***/
/*** ***/
/*** My address: ***/
/*** Richard M. Ross, Jr. ***/
/*** Eidetic Imaging ***/
/*** 740 N. 22nd Street ***/
/*** Philadelphia, PA 19130 ***/
/*** ***/
/*** Phone - (215) 236-7388 ***/
/************************************************************************/
/* compiler directives to fetch the necessary header files */
#include <exec/types.h>
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfx.h>
#include <graphics/regions.h>
#include <graphics/copper.h>
#include <graphics/gels.h>
#include <graphics/gfxbase.h>
#include <devices/keymap.h>
#include <hardware/blit.h>
/* These definitions are used by intuition for
* calls to OpenLibrary() in order to ensure
* that an appropriate ROM revision is
* available.
*/
#define INTUITION_REV 1
#define GRAPHICS_REV 1
/* Intuition always wants to see these declarations */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
/* This is the Window structure declaration.
* Nothing fancy is going on here, but note
* the Flags and IDCMPFlags members of the
* structure define which messages will be
* sent by Intuition. I haven't used them all
* and if you want to change the settings you
* should probably do it her instead of using
* ModifyIDCMP later.
*/
struct NewWindow NewWindow = {
20,
20,
300,
150,
0,
1,
CLOSEWINDOW | MOUSEMOVE | MOUSEBUTTONS | MENUPICK
| NEWSIZE | INACTIVEWINDOW | SIZEVERIFY,
WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWDRAG
| WINDOWDEPTH | WINDOWSIZING | REPORTMOUSE,
NULL,
NULL,
"AMIGA FreeDraw 0.01",
NULL,
NULL,
100, 35,
640, 200,
WBENCHSCREEN,
};
/*******************************************************************/
/* DrawBox - Simple routine to draw an unfilled rectangle */
/* It accepts the coordinates of the top-left and lower-right */
/* points of the rectangle, a pointer to the Window structure, */
/* and the color in which to render the rectangle. The current */
/* FgPen color of the window is preserved thru the call. No */
/* clipping is done. */
/*******************************************************************/
void DrawBox( tlx, tly, brx, bry, window, color )
SHORT tlx, tly; /* top-left x,y coordinates */
SHORT brx, bry; /* lower-right x,y coordinates */
struct Window *window; /* pointer to target window */
BYTE color; /* color to use for render */
{
BYTE OldColor = window->RPort->FgPen; /* save window's FgPen */
SetAPen( window->RPort, color ); /* set draw color for box */
Move(window->RPort, tlx, tly); /* move to top-left point */
Draw(window->RPort, brx, tly); /* and draw to each of the */
Draw(window->RPort, brx, bry); /* four corners of the box */
Draw(window->RPort, tlx, bry);
Draw(window->RPort, tlx, tly);
SetAPen( window->RPort, OldColor ); /* restore old FgPen */
}
/*********************************************************/
/* Color Select Menu */
/* */
/* This is where the menu for color selection is */
/* defined. It should be flexible enough to allow for */
/* increased palette sizes, but this version is only */
/* for the 4-color mode of the WorkBench screen. */
/*********************************************************/
/* A few definitions are needed here.
* Note that MAXPAL should be increased
* to allow for palette larger than
* four colors.
*/
#define ITEMSTUFF (ITEMENABLED | HIGHBOX)
#define CW 40
#define CH 25
#define MAXPAL 4
/* declare enough storage for required
* number of menu items and associated
* images. This menu will be using
* graphics renditions of menu items,
* so the Image structures must be
* declared. This menu is modeled after
* the one found in the IconEd source.
*/
struct MenuItem coloritem[MAXPAL];
struct Image colorimage[MAXPAL];
/* array of palette sizes to correspond with
* depth of window in bit-planes
*/
SHORT palette[] = { 2, 4, 8, 16, 32 };
/*****************************************************************/
/* The following function initializes the structure arrays */
/* needed to provide the Color menu topic. */
/*****************************************************************/
InitColorItems( depth )
SHORT depth; /* number of bit-planes in window */
{
SHORT n, colors;
colors = palette[depth-1];
for( n=0; n<colors; n++ ) /* loop for max number of items */
{
coloritem[n].NextItem = &coloritem[n+1];
coloritem[n].ItemFill = (APTR)&colorimage[n];
/* the next two items might be changed for
* when bit-planes is greater than 2
*/
coloritem[n].LeftEdge = 2 + CW * (n % 4);
coloritem[n].TopEdge = CH * (n / 4);
coloritem[n].Width = CW;
coloritem[n].Height = CH;
coloritem[n].Flags = ITEMSTUFF;
coloritem[n].MutualExclude = 0;
coloritem[n].SelectFill = NULL;
coloritem[n].Command = 0;
coloritem[n].SubItem = NULL;
coloritem[n].NextSelect = 0;
colorimage[n].LeftEdge = 1;
colorimage[n].TopEdge = 1;
colorimage[n].Width = CW-2;
colorimage[n].Height = CH-2;
colorimage[n].Depth = depth;
colorimage[n].ImageData = NULL;
colorimage[n].PlanePick = 0;
colorimage[n].PlaneOnOff = n;
}
coloritem[colors-1].NextItem = NULL; /* needed for last item in list */
return( 0 );
}
/*****************************************************/
/* Draw Mode Menu */
/* */
/* Here are the code and data declarations for */
/* the DrawMode menu. Current choices are limited */
/* to Erase, Filled Box, Hollow Box, and PenDraw. */
/*****************************************************/
/* define maximum number of menu items */
#define DMODEMAX 4
/* declare storage space for menu items and
* their associated IntuiText structures
*/
struct MenuItem DModeItem[DMODEMAX];
struct IntuiText DModeText[DMODEMAX];
/*****************************************************************/
/* The following function initializes the structure arrays */
/* needed to provide the DrawMode menu topic. */
/*****************************************************************/
InitDModeItems()
{
short n;
/* initialize each meu item and IntuiText with loop */
for( n=0; n<DMODEMAX; n++ )
{
DModeItem[n].NextItem = &DModeItem[n+1];
DModeItem[n].LeftEdge = 0;
DModeItem[n].TopEdge = 10 * n;
DModeItem[n].Width = 112;
DModeItem[n].Height = 10;
DModeItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX;
DModeItem[n].MutualExclude = 0;
DModeItem[n].ItemFill = (APTR)&DModeText[n];
DModeItem[n].SelectFill = NULL;
DModeItem[n].Command = 0;
DModeItem[n].SubItem = NULL;
DModeItem[n].NextSelect = 0;
DModeText[n].FrontPen = 0;
DModeText[n].BackPen = 1;
DModeText[n].DrawMode = JAM2; /* render in fore and background */
DModeText[n].LeftEdge = 0;
DModeText[n].TopEdge = 1;
DModeText[n].ITextFont = NULL;
DModeText[n].NextText = NULL;
}
DModeItem[DMODEMAX-1].NextItem = NULL;
/* initialize text for specific menu items */
DModeText[0].IText = (UBYTE *)"Erase All";
DModeText[1].IText = (UBYTE *)"Hollow Box";
DModeText[2].IText = (UBYTE *)"Filled Box";
DModeText[3].IText = (UBYTE *)"Pen Draw";
return( 0 );
}
/***************************************************/
/* Menu Definition */
/* */
/* This section of code is where the simple */
/* menu definition goes. For now it supports */
/* only Color and Drawmode selection, but new */
/* choices can easily be added by creating */
/* structures and initializations functions */
/* similar to those provided above. */
/***************************************************/
/* current number of available menu topics */
#define MAXMENU 2
/* declaration of menu structure array for
* number of current topics. Intuition
* will use the address of this array to
* set and clear the menus associated with
* the window.
*/
struct Menu menu[MAXMENU];
/**********************************************************************/
/* The following function initializes the Menu structure array with */
/* appropriate values for our simple menu strip. Review the manual */
/* if you need to know what each value means. */
/**********************************************************************/
InitMenu()
{
menu[0].NextMenu = &menu[1];
menu[0].LeftEdge = 10;
menu[0].TopEdge = 0;
menu[0].Width = 50;
menu[0].Height = 10;
menu[0].Flags = MENUENABLED;
menu[0].MenuName = "Color"; /* text for menu-bar display */
menu[0].FirstItem = &coloritem[0]; /* pointer to first item in list */
menu[1].NextMenu = NULL;
menu[1].LeftEdge = 65;
menu[1].TopEdge = 0;
menu[1].Width = 85;
menu[1].Height = 10;
menu[1].Flags = MENUENABLED;
menu[1].MenuName = "DrawMode"; /* text for menu-bar display */
menu[1].FirstItem = &DModeItem[0]; /* pointer to first item in list */
return( 0 );
}
/******************************************************/
/* Main Program */
/* */
/* This is the main body of the program. */
/******************************************************/
main()
{
struct Window *Window; /* ptr to applications window */
struct IntuiMessage *NewMessage; /* msg structure for GetMsg() */
BYTE DrawColor = 1; /* initial drawing color */
SHORT OldBRX = 30, OldBRY = 30; /* point coords used for boxes */
SHORT TLX = 20, TLY = 20; /* initial top-left point coords */
ULONG class; /* used in message monitor loop */
USHORT code; /* used in message monitor loop */
SHORT x, y, x1, y1, x2, y2; /* various coordinate variables */
SHORT MinX, MinY, MaxX, MaxY; /* clipping boundary variables */
USHORT MenuNum, ItemNum;
/* The following is a set of declarations
* for a number of flag values used by the
* program. These would perhaps be better
* coded as a bit-field for all the flags,
* but I'm lazy, and this is easier.
*/
SHORT MouseMoved = FALSE; /* indicates new mouse position ready */
SHORT KeepGoing = TRUE; /* main loop control value */
SHORT ClipIt = FALSE; /* are new point coords out of bounds? */
SHORT ClippedLast = FALSE; /* was last PenDraw operation clipped? */
SHORT PenMode = FALSE; /* indicates PenDraw mode is set */
SHORT PenDown = FALSE; /* if mouse moved, then should it draw? */
SHORT RubberBox = FALSE; /* are we currently rubberbanding a box? */
SHORT FilledBox = FALSE; /* should boxes be filled when drawn? */
/* attempt to Open Library to access Intuition */
IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", INTUITION_REV);
if( IntuitionBase == NULL )
exit(FALSE);
/* attempt to OpenLibrary to access Graphics functions */
GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library",GRAPHICS_REV);
if( GfxBase == NULL )
exit(FALSE);
/* Try to open new window for application */
if(( Window = (struct Window *)OpenWindow(&NewWindow) ) == NULL)
exit(FALSE);
/* set initial clipping boundaries
* from the values found in the window
* structure for border dimensions
*/
MinX = Window->BorderLeft;
MinY = Window->BorderTop;
MaxX = Window->Width - Window->BorderRight - 1;
MaxY = Window->Height - Window->BorderBottom - 1;
InitColorItems( 2 ); /* initialize Color menu arrays */
InitDModeItems(); /* initialize DrawMode menu arrays */
InitMenu(); /* initialize the menu structures */
/* Now, having initialized the various arrays
* of structures required for menu generation
* we can tell Intuition to make our menus
* available to the user when this window
* is active.
*/
SetMenuStrip( Window, &menu[0] );
/* set initial drw mode and color */
SetDrMd( Window->RPort, JAM1 );
SetAPen( Window->RPort, DrawColor );
/* Everything the program needs is now
* initialized and put in place. The
* program enters the following loop
* and processes message continuously as
* they are received from Intuition.
* I guess this loop is the real workhorse
* of the program. By the way, the loop
* control variable KeepGoing remains TRUE
* until a CLOSEWINDOW message is received.
* At that point it goes FALSE, and the
* program cleans up and exits.
*/
while( KeepGoing )
{
/* stay here until a message is received from Intuition */
Wait( 1 << Window->UserPort->mp_SigBit);
MouseMoved = FALSE; /* clear this flag each time thru loop */
/* since more than one message may be waiting
* a reply at this point, a loop is used to
* process all that have come in until no more
* are ready. Msg received is assigned to
* NewMessage from the GetMsg() function. This
* value will be NULL if no message is ready,
* and control passes out of the loop at that time
*/
while( NewMessage=(struct IntuiMessage *)GetMsg(Window->UserPort) )
{
/* copy some values from the message structure
* to variables used in the switch statements
* below
*/
class = NewMessage->Class;
code = NewMessage->Code;
x = Window->MouseX;
y = Window->MouseY;
/* SIZEVERIFY is a very high priority message
* in our loop and requires some immediate
* servicing. Any outstanding draw operations
* are immediately cancelled, and the DrawMode
* is nulled. This prevents any attempts to
* render outside whatever new Window boundaries
* the user chooses.
*/
if( class == SIZEVERIFY )
{
PenDown = FALSE;
if( RubberBox )
{
DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
Window->Flags &= ( 0xFFFFFFFF ^ RMBTRAP );
RubberBox = FALSE;
}
}
/* we have all the information needed from
* the message, so we can now safely reply
* to it without losing data
*/
ReplyMsg( NewMessage );
/* Examine point coords from message received
* and set the clipping flag if out of bounds.
* If user was drawing in PenMode when message
* was received, then the ClippedLast flag
* should also be set to indicate this to the
* next draw operation.
*/
if(ClipIt = ( x < MinX || x > MaxX || y < MinY || y > MaxY ))
if( PenDown )
ClippedLast = TRUE;
/* enter switch on type of message received */
switch( class )
{
case MOUSEMOVE:
/* Don't really do anything with this one
* until any other, more important, messages
* are received and processed.
*/
MouseMoved = TRUE;
break;
case NEWSIZE:
/* set new clipping boundaries */
MinX = Window->BorderLeft;
MinY = Window->BorderTop;
MaxX = Window->Width - Window->BorderRight - 1;
MaxY = Window->Height - Window->BorderBottom - 1;
break;
case CLOSEWINDOW:
/* User is ready to quit, so indicate
* that execution should terminate
* with next iteration of the loop.
*/
KeepGoing = FALSE;
break;
case MOUSEBUTTONS:
/* A number of things could have happened
* here, and further examination of data
* received from message is needed to
* determine what action should be taken.
* The code variable holds important info
* about what actually caused the message
* to be sent in the first place.
*/
switch ( code )
{
case SELECTUP:
/* User was holding down the left button
* and just released it. The PenMode
* flag variables are set accordingly.
* The pen can no longer be down, and
* ClippedLast is reset for next time.
*/
PenDown = ClippedLast = FALSE;
break;
case SELECTDOWN:
/* User has pressed the left button, and
* several differnt actions may need to
* be taken. If the ClipIt value is TRUE,
* then no action should be taken at all.
*/
if( ClipIt )
break;
/* If user is currently in PenMode, then
* set up to draw when MOUSEMOVED messages
* are received until a subsequent SELECTUP
* message comes in.
*/
if( PenMode )
{
PenDown = TRUE;
ClippedLast = FALSE;
/* make sure to set appropriate mode */
SetDrMd( Window->RPort, JAM1 );
/* and establish initial position to draw */
Move( Window->RPort, x, y );
break;
}
/* If user is currently rubberbanding a box,
* then a SELECTDOWN message means it is time
* to stop rubberbanding and actually draw it.
* The following code will be executed if
* this is the case, and it will determine if
* a filled box is needed before rendering.
*/
if( RubberBox )
{
/* set draw mode back to JAM1 since
* it is now currently set to COMPLEMENT
*/
SetDrMd( Window->RPort, JAM1 );
RubberBox = FALSE; /* turn off rubberbanding */
/* Restore the condition of the RMBTRAP
* bit in the Window structure's Flags
* member. Menubutton events will no
* be received by this loop.
*/
Window->Flags &= ( 0xFFFFFFFF ^ RMBTRAP );
/* RectFill is not condusive to the smooth
* execution of programs iit arguments are
* out of order, sot his code sorts them
* in preparation for the call.
*/
if( FilledBox )
{
/* first sort the x-coords */
if( TLX < OldBRX ) {
x1 = TLX; x2 = OldBRX; }
else {
x1 = OldBRX; x2 = TLX; }
/* then sort the y-coords */
if( TLY < OldBRY ) {
y1 = TLY; y2 = OldBRY; }
else {
y1 = OldBRY; y2 = TLY; }
/* now generate the filled rectangle */
RectFill( Window->RPort, x1, y1, x2, y2 );
}
else
{
/* FilledBox not set, so draw hollow box */
DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
}
break;
}
/* If execution comes here, then PenMode was
* not set and user was not rubberbanding.
* SELECTDOWN therefore indicates to start the
* rubberbanding process at this point. The
* initial coords are set to the values we
* received when the GetMsg() was executed.
*/
TLX = OldBRX = x; TLY = OldBRY = y;
/* set to render in XOR mode */
SetDrMd( Window->RPort, COMPLEMENT );
/* set flag to indicate we are now rubberbanding */
RubberBox = TRUE;
/* This instruction indicates to Intuition
* that we now wish to receive a message
* each time the Menubutton is pressed.
* This is how we hijack the right button
* for temporary use as a Cancel button
* instead of a Menubutton.
*/
Window->Flags |= RMBTRAP;
/* render the initial rubberbox and exit */
DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
break;
case MENUDOWN:
/* WE only receive this message class if
* the RMBTRAP flag bit has been set, so
* it always means that we should cancel
* the box which is currently rubberbanding.
*/
/* turn the flag off */
RubberBox = FALSE;
/* restore control of menubutton to Intuition */
Window->Flags &= ( 0xFFFFFFFF ^ RMBTRAP );
/* erase (by double XOR'ing) the current
* rubberbox and exit switch.
*/
DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
break;
default:
/* Something unimportant happened, so just
* continue thru the GetMsg() loop.
*/
continue;
}
break;
case MENUPICK:
/* A menu event has taken place and is
* ready to be processed. Examine the
* code variable received from the message
* to determine what action should be taken.
* The first check is for MENUNULL, which
* means that nothing should be done at all.
*/
if( code != MENUNULL )
{
/* get menu and item numbers from code */
MenuNum = MENUNUM( code );
ItemNum = ITEMNUM( code );
/* determine appropriate action by menu number */
switch ( MenuNum )
{
case 0:
/* Menu 0 is the Color menu. The
* item number indicates which new
* color to set.
*/
DrawColor = ItemNum;
SetAPen( Window->RPort, DrawColor );
break;
case 1:
/* Menu 1 is the DrawMode menu. The item
* number indicates what to do.
* NOTE: Since we cannot have received
* this message if we were rubberbanding,
* then there is no need to clean up before
* changing drawing modes.
*/
switch ( ItemNum )
{
case 0:
/* Erase window to current color */
SetDrMd( Window->RPort, JAM1 );
RectFill( Window->RPort, MinX,MinY,MaxX,MaxY);
break;
case 1:
/* set flag variables for hollow box */
PenMode = FALSE;
FilledBox = FALSE;
break;
case 2:
/* set flag variables for filled box */
PenMode = FALSE;
FilledBox = TRUE;
break;
case 3:
/* set flag variables for PenMode */
PenMode = TRUE;
break;
default:
/* don't do anything */
break;
}
break;
default:
/* Menu number unrecognized, do nothing */
break;
}
}
break;
case INACTIVEWINDOW:
/* User has de-selected our window, so a
* little bit of cleaning up may be needed
* to prevent untoward events when he comes
* back to it.
*/
/* erase any outstanding rubberbox */
if( RubberBox )
DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
/* reset all the flafg variables */
PenDown = ClippedLast = RubberBox = FALSE;
/* return possibly diverted menubutton events to Big I */
Window->Flags &= ( 0xFFFFFFFF ^ RMBTRAP );
break;
default:
/* message class was unrecognized, so do nothing */
break;
}
} /* this brace ends the while(NewMessage) loop way back when */
/* There are no more messages waiting at the
* IDCMP port, so we can now proceed to
* process any MOUSEMOVED message we may
* have received.
*/
if( MouseMoved && !ClipIt)
{
/* the mouse did move, and we don't need to clip */
/* check first if we are drawing in PenMode */
if( PenDown )
{
/* We have to examine if we clipped the
* last PenMode draw operation. If we did,
* then this is the first move back into
* window boundaries, so we mov instead of
* drawing.
*/
if( ClippedLast )
{
ClippedLast = FALSE; /* reset this flag now */
Move( Window->RPort, x, y );
}
else
Draw( Window->RPort, x, y ); /* draw to x,y coords */
}
else
{
/* We weren't in PenMode, but we still might
* be rubberbanding a box. If so, then we
* should erase the current rubberbox and
* draw a new one with the new mouse coords.
*/
if( RubberBox )
{
/* erase the old rubberbox - draw mode is COMPLEMENT */
DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
/* assign new values to box coords */
OldBRX = x; OldBRY = y;
/* and draw the new rubberbox */
DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
}
}
}
}
/* It must be time to quit, so we have to clean
* up and exit.
*/
ClearMenuStrip( Window );
CloseWindow( Window );
exit(TRUE);
}